#include "executor/system_tool_executor.h"

#include <algorithm>
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <memory>
#include <sstream>
#include <thread>
// 添加文件系统相关头文件
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <dirent.h>    // 用于遍历目录
#include <signal.h>    // 用于kill系统调用
#include <cstdio>
#include <memory>
#include <fstream>     // 用于读取/proc文件
#include <cctype>      // 用于字符处理

#include <glog/logging.h>

namespace sysinfo {
namespace monitor {

namespace {
// 定义4M缓冲区大小常量
constexpr size_t kBufferSize = 4 * 1024 * 1024;  // 4MB
constexpr int kCommmandToolsIntervalMillieconds = 50;
}  // namespace

CommandExecutionInfo CommandExecutionInfo::FromConfig(const CommandConfig& config) {
    CommandExecutionInfo exec_info;
    exec_info.name = config.name();
    exec_info.path = config.path();
    exec_info.args = config.args();
    exec_info.is_oneshot = config.oneshot();
    exec_info.need_publish = config.need_publish();
    // 不再使用interval字段，因为命令进程会持续运行
    
    // 构造完整程序路径
    exec_info.program = exec_info.path;
    if (!exec_info.program.empty() && exec_info.program.back() != '/') {
        exec_info.program += "/";
    }
    exec_info.program += exec_info.name;
    
    // 解析参数
    std::istringstream iss(exec_info.args);
    std::string arg;
    while (iss >> arg) {
        exec_info.parsed_args.push_back(arg);
    }
    
    // 打印exec_info的信息
    LOG(INFO) << "CommandExecutionInfo created: name=" << exec_info.name
              << ", path=" << exec_info.path
              << ", args=" << exec_info.args
              << ", is_oneshot=" << (exec_info.is_oneshot ? "true" : "false")
              << ", need_publish=" << (exec_info.need_publish ? "true" : "false")
              << ", program=" << exec_info.program;
    
    return exec_info;
}

std::string CommandExecutionInfo::GetFullCommand() const {
    std::string result = program;
    for (const auto& arg : parsed_args) {
        result += " " + arg;
    }
    return result;
}

SystemToolExecutor::SystemToolExecutor(const CommandConfigs& command_configs,
                                       BoundedMonitorQueue<SystemInfoProto>& system_info_queue,
                                       CircularMonitorQueue<SystemInfoProto>& system_info_circular_queue)
    : command_configs_(command_configs),
      system_info_queue_(system_info_queue),
      system_info_circular_queue_(system_info_circular_queue),
      run_ctrl_(false),
      non_reentrant_stop_(false) {
    // 区分continuous和oneshot命令
    auto execution_infos = ConvertConfigsToExecutionInfo(command_configs);
    for (const auto& exec_info : execution_infos) {
        if (exec_info.is_oneshot) {
            oneshot_execution_infos_.push_back(exec_info);
        } else {
            continuous_execution_infos_.push_back(exec_info);
        }
    }

    parser_ = std::make_unique<SystemToolParser>();
    Init();
}

SystemToolExecutor::~SystemToolExecutor() {
    // 确保资源被正确释放
    if (!non_reentrant_stop_.load()) {
        Stop();
    }
}

void SystemToolExecutor::Init() {
    // 初始化命令执行器
    LOG(INFO) << "Initializing SystemToolExecutor";

    // 验证所有命令
    for (const auto& exec_info : continuous_execution_infos_) {
        if (!ValidateCommand(exec_info)) {
            LOG(ERROR) << "Invalid continuous command: " << exec_info.program;
        }
    }
    
    for (const auto& exec_info : oneshot_execution_infos_) {
        if (!ValidateCommand(exec_info)) {
            LOG(ERROR) << "Invalid oneshot command: " << exec_info.program;
        }
    }
}

void SystemToolExecutor::Start() {
    run_ctrl_.store(false);

    // 启动持续命令
    for (const auto& exec_info : continuous_execution_infos_) {
        // 检查系统中是否已经存在相同名称的进程，如果存在则先终止
        CheckAndKillExistingProcess(exec_info);
        // 启动新的持续命令
        StartContinuousCommand(exec_info);
        
        // 保留命令之间50毫秒的启动间隔，与老项目一致
        std::this_thread::sleep_for(std::chrono::milliseconds(kCommmandToolsIntervalMillieconds));
    }
}

void SystemToolExecutor::Stop() {
    // 检查是否已经停止过
    if (non_reentrant_stop_.load()) {
        return;
    }

    LOG(INFO) << "Stopping SystemToolExecutor";
    run_ctrl_.store(true);
    non_reentrant_stop_.store(true);

    // 终止所有进程
    TerminateAllProcesses();

    // 清理子进程管理表
    {
        std::lock_guard<std::mutex> lock(subprocess_mutex_);
        sub_processes_.clear();
    }

    // 等待所有线程结束
    for (auto& thread : worker_threads_) {
        if (thread.joinable()) {
            thread.join();
        }
    }
    worker_threads_.clear();
    LOG(INFO) << "SystemToolExecutor stopped";
}

void SystemToolExecutor::StartOnce() {
    // 执行一次性命令
    for (const auto& exec_info : oneshot_execution_infos_) {
        ExecuteOneshotCommand(exec_info);

        // 保留命令之间50毫秒的启动间隔，与老项目一致
        std::this_thread::sleep_for(std::chrono::milliseconds(kCommmandToolsIntervalMillieconds));
    }
}

void SystemToolExecutor::StartContinuousCommand(const CommandExecutionInfo& exec_info) {
    // 启动命令执行任务
    worker_threads_.emplace_back([this, exec_info]() {
        RunContinuousProcess(exec_info);
    });
}

void SystemToolExecutor::RunContinuousProcess(const CommandExecutionInfo& exec_info) {
    std::string command_name = exec_info.name.empty() ? exec_info.program : exec_info.name;
    LOG(INFO) << "Running continuous process: " << command_name;

    // 创建管道
    int pipefd[2];
    if (pipe(pipefd) == -1) {
        LOG(ERROR) << "Pipe creation failed: " << strerror(errno);
        return;
    }

    // 创建子进程
    pid_t pid = fork();
    if (pid == -1) {
        LOG(ERROR) << "Fork failed: " << strerror(errno);
        close(pipefd[0]);
        close(pipefd[1]);
        return;
    }

    if (pid == 0) {
        // 子进程
        // 关闭读端
        close(pipefd[0]);
        
        // 重定向标准输出和标准错误到管道写端
        dup2(pipefd[1], STDOUT_FILENO);
        dup2(pipefd[1], STDERR_FILENO);
        
        // 注意：不要关闭pipefd[1]，否则子进程写入时会收到SIGPIPE信号
        
        // 构造命令参数数组
        std::vector<char*> argv;
        // argv[0]是命令名
        argv.push_back(const_cast<char*>(exec_info.name.c_str()));
        for (const auto& arg : exec_info.parsed_args) {
            argv.push_back(const_cast<char*>(arg.c_str()));
        }
        argv.push_back(nullptr);

        // 执行命令
        execv(exec_info.program.c_str(), argv.data());

        // 如果execv返回，说明执行失败
        LOG(ERROR) << "Failed to execute command: " << exec_info.program << " (" << strerror(errno) << ")";
        exit(1);
    } else {
        // 父进程
        // 关闭写端，只读取
        close(pipefd[1]);
        
        // 保存子进程PID
        {
            std::lock_guard<std::mutex> lock(subprocess_mutex_);
            sub_processes_[exec_info].pid = pid;
            sub_processes_[exec_info].name = command_name;
        }

        // 读取子进程输出
        char buffer[kBufferSize];
        std::string accumulated_output;
        ssize_t bytes_read;
        while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer) - 1)) > 0 && !run_ctrl_.load()) {
            buffer[bytes_read] = '\0';
            accumulated_output.append(buffer, bytes_read);
            
            // 按行处理输出
            size_t pos;
            while ((pos = accumulated_output.find('\n')) != std::string::npos) {
                std::string line = accumulated_output.substr(0, pos + 1);
                accumulated_output.erase(0, pos + 1);
                
                // 将每一行传递给解析器处理
                ParseContinuousOutput(exec_info, line);
            }
        }
        
        // 处理最后剩余的输出（如果有）
        if (!accumulated_output.empty()) {
            ParseContinuousOutput(exec_info, accumulated_output);
        }
        
        // 关闭读端
        close(pipefd[0]);
        
        // 等待子进程结束
        int status;
        waitpid(pid, &status, 0);
        
        // 从子进程管理表中移除
        {
            std::lock_guard<std::mutex> lock(subprocess_mutex_);
            sub_processes_.erase(exec_info);
        }
        
        LOG(INFO) << "Parse loop exited for: " << command_name;
    }
}

void SystemToolExecutor::ExecuteOneshotCommand(const CommandExecutionInfo& exec_info) {
    std::thread oneshot_thread([this, exec_info]() {
        // 执行oneshot命令
        ExecutionResult result = ExecuteSync(exec_info);

        if (result.success) {
            ParseOneshotOutput(exec_info, result.output);
        } else {
            LOG(ERROR) << "Failed to execute oneshot command: " << exec_info.name
                        << ", error: " << result.error_message;
        }
    });
    
    // 分离线程，让其独立运行并自行结束
    oneshot_thread.detach();
}

ExecutionResult SystemToolExecutor::ExecuteSync(const CommandExecutionInfo& exec_info) const {
    ExecutionResult result;
    
    // 构造完整命令
    std::string command = exec_info.GetFullCommand() + " 2>&1";
    LOG(INFO) << "Executing oneshot command: " << command;
    
    // 执行命令并捕获输出
    FILE* pipe = popen(command.c_str(), "r");
    if (!pipe) {
        result.success = false;
        result.error_message = "Failed to execute command";
        LOG(ERROR) << "popen failed for command: " << command;
        return result;
    }

    try {
        // 读取输出
        char buffer[kBufferSize];
        while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
            result.output += buffer;
        }

        // 检查命令执行结果
        int exit_code = pclose(pipe);
        result.exit_code = WEXITSTATUS(exit_code);
        result.success = (result.exit_code == 0);

        if (result.success) {
            LOG(INFO) << "Oneshot command completed successfully: " << exec_info.name
                      << ", output size: " << result.output.size() << " bytes";
        } else {
            LOG(ERROR) << "Oneshot command failed: " << exec_info.name
                       << ", exit code: " << result.exit_code;
        }
    } catch (const std::exception& e) {
        result.success = false;
        result.error_message = e.what();
        LOG(ERROR) << "Exception during oneshot execution: " << e.what();
    }

    return result;
}


void SystemToolExecutor::ParseContinuousOutput(const CommandExecutionInfo& exec_info,
                                              const std::string& output) {
    // 解析并处理输出（跳过空行）
    // 空行定义：只包含换行符或完全为空的行
    if (output.empty() || output == "\n") {
        return;
    }

    if (exec_info.need_publish) {
        SystemInfoProto system_info_proto;
        if (parser_ && parser_->Parse(exec_info.name, output, &system_info_proto)) {
            system_info_queue_.Put(system_info_proto);
            LOG_EVERY_N(INFO, 1000) << "Publishing continuous command data to system info queue: "
                                    << exec_info.name;
        } else {
            LOG(ERROR) << "Failed to parse output for command: " << exec_info.name;
        }
    } else {
        // 直接打印输出
        LOG(INFO) << "[DIRECT PRINT] " << exec_info.name << " >> " << output;
    }
}

void SystemToolExecutor::ParseOneshotOutput(const CommandExecutionInfo& exec_info,
                                           const std::string& output) {
    if (exec_info.need_publish) {
        SystemInfoProto system_info_proto;
        if (parser_ && parser_->Parse(exec_info.name, output, &system_info_proto)) {
            // 一次性任务结果放入循环队列
            system_info_circular_queue_.Put(system_info_proto);
            LOG(INFO) << "Publishing oneshot command data to circular queue: " << exec_info.name;
        } else {
            LOG(ERROR) << "Failed to parse oneshot command output: " << exec_info.name;
        }
    } else {
        // 直接打印输出
        LOG(INFO) << "[DIRECT PRINT] " << exec_info.name << " >> \n" << output << "\n";
    }
}

bool SystemToolExecutor::ValidateCommand(const CommandExecutionInfo& exec_info) const {
    if (exec_info.program.empty()) {
        LOG(ERROR) << "Command program is empty";
        return false;
    }

    // 检查命令是否存在且可执行
    struct stat st;
    if (stat(exec_info.program.c_str(), &st) != 0) {
        LOG(ERROR) << "Command not found: " << exec_info.program;
        return false;
    }

    // 检查是否为普通文件且具有可执行权限
    if (!S_ISREG(st.st_mode) || !(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) {
        LOG(ERROR) << "Command is not executable: " << exec_info.program;
        return false;
    }
    
    return true;
}

std::vector<CommandExecutionInfo> SystemToolExecutor::ConvertConfigsToExecutionInfo(
    const CommandConfigs& configs) const {
    std::vector<CommandExecutionInfo> execution_infos;
    std::set<CommandExecutionInfo> seen_configs;

    for (const auto& config : configs) {
        auto exec_info = CommandExecutionInfo::FromConfig(config);

        // 检查重复配置
        if (seen_configs.find(exec_info) != seen_configs.end()) {
            LOG(ERROR) << "Duplicate command configuration detected and skipped: "
                       << "name='" << config.name() << "', "
                       << "path='" << config.path() << "', "
                       << "args='" << config.args() << "'";
            continue;
        }

        seen_configs.insert(exec_info);
        execution_infos.push_back(exec_info);
    }

    return execution_infos;
}

void SystemToolExecutor::TerminateAllProcesses() {
    LOG(INFO) << "Terminating all subprocesses, count: " << sub_processes_.size();

    std::lock_guard<std::mutex> lock(subprocess_mutex_);

    for (const auto& pair : sub_processes_) {
        const SubProcess& sub_process = pair.second;
        if (sub_process.pid > 0) {
            LOG(INFO) << "Terminating process: " << sub_process.name
                      << ", PID: " << sub_process.pid;

            // 先尝试优雅终止
            kill(sub_process.pid, SIGTERM);
        }
    }

    // 等待一段时间让进程优雅退出
    std::this_thread::sleep_for(std::chrono::milliseconds(100));

    // 强制终止仍然存活的进程
    for (const auto& pair : sub_processes_) {
        const SubProcess& sub_process = pair.second;
        if (sub_process.pid > 0) {
            // 检查进程是否还在运行
            int status;
            pid_t result = waitpid(sub_process.pid, &status, WNOHANG);
            if (result == 0) {
                // 进程仍在运行，强制终止
                LOG(INFO) << "Force killing process: " << sub_process.name
                          << ", PID: " << sub_process.pid;
                kill(sub_process.pid, SIGKILL);
                // 清理僵尸进程
                waitpid(sub_process.pid, &status, 0);
            }
        }
    }

    sub_processes_.clear();
}

void SystemToolExecutor::CheckAndKillExistingProcess(const CommandExecutionInfo& exec_info) {
    // 直接使用exec_info.name作为程序名
    const std::string& program_name = exec_info.name;

    // 通过遍历/proc文件系统查找同名进程
    DIR* proc_dir = opendir("/proc");
    if (!proc_dir) {
        LOG(ERROR) << "Failed to open /proc directory";
        return;
    }

    struct dirent* entry;
    std::vector<pid_t> pids_to_kill;

    // 遍历/proc目录中的所有PID目录
    while ((entry = readdir(proc_dir)) != nullptr) {
        // 检查是否为PID目录（纯数字）
        if (entry->d_type == DT_DIR && std::isdigit(entry->d_name[0])) {
            pid_t pid = atoi(entry->d_name);
            if (pid <= 0 || pid == getpid()) {
                continue; // 跳过无效PID和自身
            }

            // 构造/proc/[pid]/comm文件路径来获取进程名
            std::string comm_path = "/proc/" + std::string(entry->d_name) + "/comm";
            std::ifstream comm_file(comm_path);
            if (comm_file.is_open()) {
                std::string comm_name;
                std::getline(comm_file, comm_name);
                if (comm_name == program_name) {
                    pids_to_kill.push_back(pid);
                }
                comm_file.close();
            }
        }
    }

    closedir(proc_dir);

    // 终止找到的进程
    for (pid_t pid : pids_to_kill) {
        LOG(INFO) << "Found existing process for " << program_name
                  << " with PID: " << pid << ". Killing it.";

        // 先尝试优雅终止
        if (kill(pid, SIGTERM) == 0) {
            // 等待一小段时间让进程优雅退出
            std::this_thread::sleep_for(std::chrono::milliseconds(100));

            // 检查进程是否还在运行
            if (kill(pid, 0) == 0) {
                // 进程仍在运行，强制终止
                LOG(INFO) << "Force killing process " << pid;
                kill(pid, SIGKILL);
            }
        } else {
            LOG(ERROR) << "Failed to send SIGTERM to process " << pid;
        }
    }
}

}  // namespace monitor
}  // namespace qcraft